package com.spring;

import com.spring.AOP.AopInterface.ProxyFactory;
import com.spring.AOP.DefaultProxyFactory;
import com.spring.springAnnotation.Autowired;
import com.spring.springAnnotation.PostConstruct;
import com.spring.springInterface.*;

import java.lang.reflect.*;
import java.util.*;

public class DefaultBeanFactory implements BeanFactory {
    private DefaultBeanDefinitionRegistry registry;
    private Map<String, BeanDefinition> beanDefinitionMap ;
    ArrayList<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();
    HashMap<Class<?>, List<String>> typeMap = new HashMap<>();
    private ProxyFactory proxyFactory;
    private ConstructorFinder constructorFinder;
    //销毁方法
    private final Map<String, DestroyMethodInfo> disposableBeans = new HashMap<>();


    //一级缓存:单例池
    HashMap<String, Object> singletonObjects = new HashMap<>();
    // 二级缓存：存放早期暴露的Bean（半成品，已实例化但未初始化）
    private final Map<String, Object> earlySingletonObjects = new HashMap<>();
    // 三级缓存：存放ObjectFactory（用于生成早期引用）
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>();

    //creatingSet，存放正在创建的Bean，判断是否出现循环依赖
    private final Set<String> creatingSet = new HashSet<>();


//不启用aop
    public DefaultBeanFactory() {
        this.registry = new DefaultBeanDefinitionRegistry();
        this.beanDefinitionMap= registry.getBeanDefinitions();
        this.proxyFactory = null;
        this.constructorFinder = new ConstructorMaker();
        constructorFinder.setBeanFactory(this);
    }
//启用aop
    public DefaultBeanFactory(DefaultBeanDefinitionRegistry registry) {
        this.registry = registry;
        this.beanDefinitionMap= registry.getBeanDefinitions();
        this.proxyFactory = new DefaultProxyFactory(beanDefinitionMap);
        this.constructorFinder = new ConstructorMaker();
        constructorFinder.setBeanFactory(this);
    }

    @Override
    public Object getBean(String beanName) throws Exception {
        //一级缓存
        Object singleton = singletonObjects.get(beanName);
        if (singleton != null) {
            return singleton;
        }
        //单例池没有：多例或者bean还没实例化
        DefaultBeanDefinition beanDefinition = (DefaultBeanDefinition) beanDefinitionMap.get(beanName);
        if (beanDefinition == null) {
            throw new Exception("beanName:" + beanName + "不存在");
        }
        if (beanDefinition.getScope().equals("singleton")) {
            // 2. 检查二级缓存中是否有早期暴露的Bean
            singleton = earlySingletonObjects.get(beanName);
            if (singleton != null) {
                return singleton;
            }
        }
        // 3. 检查三级缓存中是否有ObjectFactory
        ObjectFactory<?> singletonFactory =  singletonFactories.get(beanName);
        if (singletonFactory != null) {
            // 从工厂获取早期引用（可能是原始对象，也可能是代理对象）
            singleton = singletonFactory.getObject();
            // 将获取到的对象提升到二级缓存，并移除三级缓存中的工厂
            earlySingletonObjects.put(beanName, singleton);
            singletonFactories.remove(beanName);
            return singleton;
        }
        if (beanDefinition.getScope().equals("singleton")) {
            // 4. 如果所有缓存都没有，则创建Bean
            //标记为正在创建中
            creatingSet.add(beanName);
            singleton = createBean(beanName, beanDefinition);
            //如果出现了循环依赖
            // 我们需要检查并使用它，而不是用 createBean 返回的可能过时的原始对象。
            Object exposedObject = earlySingletonObjects.get(beanName);
            if (exposedObject != null) {
                singleton = exposedObject;
            }
             singletonObjects.put(beanName, singleton);
            // 清理缓存
            creatingSet.remove(beanName);
            earlySingletonObjects.remove(beanName);
            singletonFactories.remove(beanName);
            return singleton;

        } else {
            // 多例直接创建
            return createBean(beanName, beanDefinition);
        }
    }
    @Override
    public Object createBean(String beanName, DefaultBeanDefinition beanDefinition) throws Exception {
// 5. 实例化前扩展点：执行后置处理器的postProcessBeforeInstantiation
        Object bean = resolveBeforeInstantiation(beanName, beanDefinition);
        if (bean != null) {
            // 如果后置处理器返回了对象，直接使用该对象（跳过后续实例化、属性注入等流程）
            registerDestroyMethod(beanName, bean, beanDefinition);
            return bean;
        }
        Object configInstance = beanDefinition.getProperties().get(beanName);
        Object beanMethod = beanDefinition.getProperties().get(beanName);
        Class<?> type = beanDefinition.getBeanClass();
        if (configInstance != null && beanMethod != null) {
            // 2.2 解析@Bean方法的参数（依赖注入）
            Object[] methodParams = resolveBeanMethodParameters((Method) beanMethod);
            // 2.3 调用@Bean方法，创建Bean实例
            bean = ((Method) beanMethod).invoke(configInstance, methodParams);
        } else {
            //6 推断构造方法
            //获取构造方法
            Constructor<?> constructor = constructorFinder.findConstructors(type);
            Object[] constructorParameters = constructorFinder.getConstructorParameters(constructor);

// 5.1实例化对象
            bean = constructor.newInstance(constructorParameters);
            if (beanDefinition.getScope().equals("singleton")) {
                //第三级缓存
                ObjectFactory<?> earlyBeanReference = getObjectFactory(beanName, beanDefinition, bean);
                singletonFactories.put(beanName, earlyBeanReference);
            }
        }
//3.2  TODO:BeanPostProcessor  后置处理
//5.2 TODO:实例化后
//7填充属性
            //属性注入
            for (Field f : type.getDeclaredFields()) {
                if (f.isAnnotationPresent(Autowired.class)) {
                    f.setAccessible(true);
                    f.set(bean, getBean(f.getName()));
                }
            }
            //填充属性后
            //8 Aware方法回调
            if (bean instanceof BeanNameAware) {
                ((BeanNameAware) bean).setBeanName(beanName);
            }
            for (Method m : type.getMethods()) {
                if (m.isAnnotationPresent(PostConstruct.class)) {
                    m.invoke(bean);
                }
            }

//9.初始化
            //初始化前
            for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                bean = beanPostProcessor.postProcessBeforeInitialization(bean, beanName);
            }
            //初始化
            if (bean instanceof InitialnizeBean) {
                ((InitialnizeBean) bean).afterPropertiesSet();
            }
            //初始化后
            for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
                bean = beanPostProcessor.postProcessAfterInitialization(bean, beanName);
            }
            //10.注册销毁方法
            registerDestroyMethod(beanName, bean, beanDefinition);
            return bean;
        }


    private Object[] resolveBeanMethodParameters(Method beanMethod) throws Exception {
        Parameter[] parameters = beanMethod.getParameters();
        Object[] params = new Object[parameters.length];

        for (int i = 0; i < parameters.length; i++) {
            Parameter param = parameters[i];
            Class<?> paramType = param.getType();
            // 按参数类型从容器中获取Bean（可扩展支持@Qualifier）
            params[i] = getBean(paramType);
        }
        return params;
    }

    private Object resolveBeforeInstantiation(String beanName, DefaultBeanDefinition beanDefinition) throws ClassNotFoundException {
        Class<?> beanClass = beanDefinition.getBeanClass();
        Object result = null;
        // 遍历所有后置处理器，执行实例化前逻辑
        for (BeanPostProcessor processor : beanPostProcessorList) {
            // 调用后置处理器的实例化前方法
            result = processor.postProcessBeforeInstantiation(beanClass, beanName);
            // 如果某个处理器返回了非null对象，直接使用该对象（中断后续处理器）
            if (result != null) {
                // 对提前返回的对象执行初始化后处理（如AOP代理）
                for (BeanPostProcessor pp : beanPostProcessorList) {
                    result = pp.postProcessAfterInitialization(result, beanName);
                }
                return result;
            }
        }

        // 所有处理器都返回null，继续正常实例化流程
        return null;
    }

    private ObjectFactory<?> getObjectFactory(String beanName, DefaultBeanDefinition beanDefinition, Object bean) {
        return () -> {
            // 检查是否正在创建（循环依赖标志）
            if (isCreating(beanName)) {
                if(proxyFactory.needAopProxy(beanName, bean)) {
                    System.out.println("提前aop");
                    return proxyFactory.createProxyIfNeedAop(bean, beanName);
                }

                return bean;
            }else{
                return bean;
            }
        };
    }
    private boolean isCreating(String beanName) {
        return creatingSet.contains(beanName);
    }
    public void initializeSingletonBean () {
        //单例初始化
        for (String beanName : beanDefinitionMap.keySet()) {
            DefaultBeanDefinition beanDefinition = (DefaultBeanDefinition) beanDefinitionMap.get(beanName);
            if (beanDefinition.getScope().equals("singleton")) {
                try {
                    singletonObjects.put(beanName, getBean(beanName));
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }
    private void registerDestroyMethod(String beanName, Object bean, DefaultBeanDefinition beanDefinition) {
        DestroyMethodInfo destroyMethodInfo = null;
        if (bean instanceof DisposableBean) {
            destroyMethodInfo = new DestroyMethodInfo(
                    () -> ((DisposableBean) bean).destroy() // 封装接口的destroy方法
            );
        }
        // 若存在销毁方法，存入disposableBeans
        if (destroyMethodInfo != null) {
            disposableBeans.put(beanName, destroyMethodInfo);
        }
    }




    //----------------------不重要的方法-------------------------
    public void destroySingletons() throws Exception {
        List<String> beanNames = new ArrayList<>(disposableBeans.keySet());
        Collections.reverse(beanNames);
        for (String beanName : beanNames) {
            DestroyMethodInfo destroyInfo = disposableBeans.get(beanName);
            // 执行销毁逻辑
            destroyInfo.executeDestroy();
        }
        disposableBeans.clear(); // 清空缓存
        singletonObjects.clear();
    }

    public ProxyFactory getProxyFactory() {
        return proxyFactory;
    }

    public void setProxyFactory(ProxyFactory proxyFactory) {
        this.proxyFactory = proxyFactory;
    }
    public Object getBeanWithoutPostProcessing (String beanName) throws Exception {
// 检查单例池中是否已经存在
        if (singletonObjects.containsKey(beanName)) {
            return singletonObjects.get(beanName);
        }

        BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
        if (beanDefinition == null) {
            throw new Exception("No bean named '" + beanName + "' is defined");
        }
        // 创建bean
        Object bean = CreateBeanWithoutPostProcessors(beanName, beanDefinition);

        initializeBeanWithoutPostProcessors(bean, beanName, beanDefinition);

        // 如果是单例，加入到单例池
        if (beanDefinition.getScope().equals("singleton")) {
            singletonObjects.put(beanName, bean);
        }

        return bean;
    }
    private Object CreateBeanWithoutPostProcessors (String beanName, BeanDefinition beanDefinition) throws Exception
    {
        //5 TODO：实例化前
        Class type = beanDefinition.getBeanClass();
        //6 推断构造方法
        //获取构造方法
        Constructor<?> constructor =constructorFinder.findConstructors(type);
        Object[] constructorParameters = constructorFinder.getConstructorParameters(constructor);
// 5.1实例化对象
        Object bean = constructor.newInstance(constructorParameters);
//7填充属性
        //属性注入
        for (Field f : type.getDeclaredFields()) {
            if (f.isAnnotationPresent(Autowired.class)) {
                f.setAccessible(true);
                // 改为调用特殊的方法来获取依赖
                Object value = getBeanWithoutPostProcessing(f.getName()); // 这里也要用特殊方法
                f.set(bean, value);
            }
        }
        //填充属性后
        for (Method m : type.getMethods()) {
            if (m.isAnnotationPresent(PostConstruct.class)) {
                m.invoke(bean);
            }
        }
        return bean;

    }
    private void initializeBeanWithoutPostProcessors (Object bean, String beanName, BeanDefinition beanDefinition) throws
            Exception {
        // 只执行Aware接口的回调（如果需要）
        if (bean instanceof BeanNameAware) {
            ((BeanNameAware) bean).setBeanName(beanName);
        }
        // 简单实现：先跳过所有初始化，或者只执行最基本的初始化
        try {
            if (bean instanceof InitialnizeBean) {
                ((InitialnizeBean) bean).afterPropertiesSet();
            }
        } catch (Exception e) {
            throw new Exception("Invocation of init method failed", e);
        }
    }
    @Override
    public <T> T getBean(Class < T > requiredType) throws Exception {
        List<String> candidateNames = typeMap.get(requiredType);
        if (candidateNames == null || candidateNames.isEmpty()) {
            throw new Exception("No bean of type [" + requiredType.getName() + "] found");
        }
        if (candidateNames.size() > 1) {
            throw new Exception("Expected single bean but found " + candidateNames.size() + ": " + candidateNames);
        }
        String beanName = candidateNames.get(0);
        return (T) getBean(beanName);
    }
    public DefaultBeanDefinitionRegistry getRegistry () {
        return registry;
    }
    public void setRegistry (DefaultBeanDefinitionRegistry registry){
        this.registry = registry;
    }
    public ArrayList<BeanPostProcessor> getBeanPostProcessorList () {
        return beanPostProcessorList;
    }
    public void setBeanPostProcessorList (ArrayList < BeanPostProcessor > beanPostProcessorList) {
        this.beanPostProcessorList = beanPostProcessorList;
    }
    public Map<String, BeanDefinition> getBeanDefinitionMap () {
        return beanDefinitionMap;
    }
    public void setBeanDefinitionMap (HashMap < String, BeanDefinition > beanDefinitionMap){
        this.beanDefinitionMap = beanDefinitionMap;
    }
    public HashMap<Class<?>, List<String>> getTypeMap () {
        return typeMap;
    }
    public void setTypeMap (HashMap < Class < ? >, List < String >> typeMap){
        this.typeMap = typeMap;
    }
    public HashMap<String, Object> getSingletonObjects () {
        return singletonObjects;
    }
    public void setSingletonObjects (HashMap < String, Object > singletonObjects){
        this.singletonObjects = singletonObjects;
    }
    @Override
    public boolean containsBean (String name){
        return beanDefinitionMap.containsKey(name);
    }
    @Override
    public boolean isSingleton (String name){
        return beanDefinitionMap.get(name).getScope().equals("singleton");
    }
    @Override
    public void addBeanPostProcessor (BeanPostProcessor processor){
        beanPostProcessorList.add(processor);
    }
}

